package poo.date;

import java.util.*;

public class Data implements Comparable {

	public static final int GIORNO = 0, MESE = 1, ANNO = 2;
	private final int G, M, A;

	public Data() {// costruttore di default, inizializza alla data odierna
		GregorianCalendar gc = new GregorianCalendar();
		G = gc.get(GregorianCalendar.DAY_OF_MONTH);
		M = gc.get(GregorianCalendar.MONTH) + 1;
		A = gc.get(GregorianCalendar.YEAR);
	}

	public Data(int g, int m, int a) {
		if (g < 1 || m < 1 || a < 0 || m > 12 || g > durataMese(m, a))
			throw new IllegalArgumentException();
		{
			this.G = g;
			this.M = m;
			this.A = a;

		}

	}

	public Data(Data d) {
		G = d.G;
		M = d.M;
		A = d.A;
	}

	public static int durataMese(int m, int a) {

		if (m < 0 || m > 12 || a < 0)
			throw new IllegalArgumentException();

		int dur;

		switch (m) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			dur = 31;
			break;

		case 2:
			dur = bisestile(a) ? 29 : 28;
			break;

		default:
			dur = 30;

		}

		return dur;
	}// durata

	public static boolean bisestile(int a) {
		if (a < 0)
			throw new IllegalArgumentException();
		if (a % 4 != 0)
			return false;
		if (a % 100 == 0 && a % 400 != 0)
			return false;

		return true;
	}

	public enum Elem {
		GIORNO, MESE, ANNO
	};

	public int get(Elem cosa) {

		switch (cosa) {
		case GIORNO:
			return G;
		case MESE:
			return M;
		default:
			return A;
		}

	}// get

	public String toString() {
		return "" + G + "/" + M + "/" + A;

	}// toString

	public Data giornoDopo() {
		int gg, mm, aa;
		if (this.G == durataMese(M, A)) {
			gg = 1;
			if (this.M == 12) {
				mm = 1;
				aa = A + 1;
			} else {
				mm = M + 1;
				aa = A;
			}

		} else {
			gg = G + 1;
			mm = M;
			aa = A;

		}
		return new Data(gg, mm, aa);

	}// giornodopo

	public int distanza(Data d) {

		int distanza = 0;

		Data d1 = new Data(this);

		while (d1.A < d.A) {
			d1 = d1.giornoDopo();
			distanza++;
		}
		while (d1.M < d.M) {
			d1 = d1.giornoDopo();
			distanza++;
		}
		while (d1.G < d.G) {
			d1 = d1.giornoDopo();
			distanza++;
		}

		while (d1.A > d.A) {
			d1 = d1.giornoPrima();
			distanza++;
		}
		while (d1.M > d.M) {
			d1 = d1.giornoPrima();
			distanza++;
		}
		while (d1.G > d.G) {
			d1 = d1.giornoPrima();
			distanza++;
		}

		return distanza;

	}

	public Data giornoPrima() {
		int gg, mm, aa;
		if (this.G == 1) {

			mm = M - 1;
			aa = A;
			gg = durataMese(mm, aa);

			if (this.M == 1) {
				mm = 12;
				aa = A - 1;
				gg = durataMese(mm, aa);
			}
		} else {
			gg = G - 1;
			mm = M;
			aa = A;
		}
		return new Data(gg, mm, aa);

	}// giornoprima

	public static void main(String[] args) {
		Data oggi = new Data();
		int g = oggi.get(Data.Elem.GIORNO);
		System.out.println(g);

		Data d = new Data();
		d.giornoPrima();
		System.out.println(d);

	}

	@Override
	public int compareTo(Object x) {

		Data d = (Data) x;
		if (this.A < d.A || this.A == d.A && this.M < d.M || this.A == d.A
				&& this.M < d.M && this.G < d.G)
			return -1;
		if (this.equals(d))
			return 0;
		return 1;
	}

	@Override
	public boolean equals(Object o) {
		if (!(o instanceof Data))
			return false;
		if (o == this)
			return true;
		Data d = (Data) o;

		return this.G == d.G && this.M == d.M && this.A == d.A;

	}

	@Override
	public int hashCode() {
		final int primo = 41;
		int h = 0;
		h = h * primo + G;
		h = h * primo + M;
		h = h * primo + A;

		return h;

	}

}